#include <iostream>
#include <vector>
#include <string>
#include <thread>
// 线程安全问题，使用互斥锁
#include <mutex>
// 原子操作问题，提供线程安全的操作方法
#include <atomic>
// 字符串处理相关（如memset等）
#include <cstring>
// 算法相关，提供find等算法支持
#include <algorithm>

// 平台相关头文件引入
#ifdef _WIN32
    // Windows平台头文件
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // 链接Windows socket库
#else
    // Linux/Unix平台头文件
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
// 为Windows提供的兼容层定义
//在当前的代码环境中通过在Linux/Unix环境下，将类型 SOCKET 定义为 int 类型；
//从而使使用该 SOCKET 类型变量的代码能够在不需要修改的情况下在对应的平台正确编译
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#endif

/**
 * 聊天服务器类 - 封装服务器功能
 */
class ChatServer {
private:
    // 服务器套接字（跨平台类型）
    SOCKET server_socket;
    // 存储客户端套接字的列表
    std::vector<SOCKET> clients;
    // 保护客户端列表的互斥锁
    std::mutex clients_mutex;
    // 控制服务器状态的标志（原子变量保证线程安全）
    std::atomic<bool> running{ true };
    const int MAX_CLIENTS = 10;    // 最大客户端连接数量
    const int BUFFER_SIZE = 2048;    // 消息缓冲区大小设置

public:
    /**
     * 构造函数 - 初始化服务器套接字
     */
    ChatServer() : server_socket(INVALID_SOCKET) {
        // 初始化网络库（Windows平台需要）
#ifdef _WIN32
        WSADATA wsaData;
        // 初始化Winsock 2.2版本
        if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
            std::cerr << "WSAStartup failed" << std::endl;
        }
#endif
    }

    /**
     * 析构函数 - 释放资源
     */
    ~ChatServer() {
        // 停止服务器并清理资源
        stop();

        // Windows平台清理Winsock
#ifdef _WIN32
        WSACleanup();
#endif
    }

    /**
     * 启动服务器
     * @param port 服务器监听端口
     * @return 启动是否成功
     */
    bool start(int port) {
        // 创建TCP套接字
        // AF_INET: IPv4地址族, SOCK_STREAM: TCP套接字
        server_socket = socket(AF_INET, SOCK_STREAM, 0);

        // 检查套接字创建是否成功
        if (server_socket == INVALID_SOCKET) {
            std::cerr << "创建套接字失败" << std::endl;
            return false;
        }

        // 设置套接字选项：允许地址重用
        int opt = 1;
#ifdef _WIN32
        setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));
#else
        setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
#endif

        // 设置服务器地址结构
        struct sockaddr_in server_addr;
        // IPv4地址族
        server_addr.sin_family = AF_INET;
        // 监听所有接口
        server_addr.sin_addr.s_addr = INADDR_ANY;
        //将主机字节序转换为网络字节序
        server_addr.sin_port = htons(port);

        // 绑定套接字到指定地址和端口
        if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) {
            std::cerr << "绑定失败" << std::endl;
            // 关闭套接字
            closesocket(server_socket);
            server_socket = INVALID_SOCKET;
            return false;
        }

        // 开始监听连接，最大等待数为MAX_CLIENTS
        if (listen(server_socket, MAX_CLIENTS) == SOCKET_ERROR) {
            std::cerr << "监听失败" << std::endl;
            // 关闭套接字
            closesocket(server_socket);
            server_socket = INVALID_SOCKET;
            return false;
        }

        // 输出服务器启动成功信息
        std::cout << "服务器启动成功，端口: " << port << std::endl;
        std::cout << "支持Windows和Linux客户端连接" << std::endl;
        return true;
    }

    /**
     * 处理客户端连接的线程函数
     * @param client_socket 客户端套接字
     * @param client_name 客户端名称
     */
    void handle_client(SOCKET client_socket, const std::string& client_name) {
        // 消息缓冲区
        char buffer[2048];
        std::string buffer_final;

        // 消息接收循环
        while (running) {
            // 清空缓冲区
            memset(buffer, 0, BUFFER_SIZE);

            // 接收客户端消息（跨平台）
#ifdef _WIN32
            int bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);
#else
            ssize_t bytes_received = recv(client_socket, buffer, BUFFER_SIZE, 0);
#endif

            // 连接断开
            if (bytes_received <= 0) {
                // 客户端关闭连接或出错
                remove_client(client_socket);
                std::cout << client_name << " 已断开连接" << std::endl;
                // 关闭客户端套接字
                closesocket(client_socket);
                return;
            }

            // 确保消息以null结尾
            buffer[bytes_received] = '\0';
            buffer_final += buffer;
            if (buffer_final.find('\n') != std::string::npos)
            {
                broadcast_message(client_socket, client_name + ":" + buffer_final);
                buffer_final.clear();
            };
            // 广播消息给所有客户端
            //broadcast_message(client_socket, client_name + ": " + std::string(buffer));
        }
    }

    /**
     * 广播消息给所有客户端（除发送者）
     * @param sender_socket 消息发送者的套接字
     * @param message 要广播的消息
     */
    void broadcast_message(SOCKET sender_socket, const std::string& message) {
        // 锁定客户端列表
        std::lock_guard<std::mutex> lock(clients_mutex);

        // 遍历所有客户端
        for (SOCKET client : clients) {
            // 不向消息发送者本身发送
            if (client != sender_socket) {
                // 发送消息给客户端
#ifdef _WIN32
                send(client, message.c_str(), (int)message.length(), 0);
#else
                send(client, message.c_str(), message.length(), 0);
#endif
            }
        }

        // 在服务器控制台显示广播的消息
        std::cout << "广播消息: " << message;
    }

    /**
     * 从客户端列表中移除客户端
     * @param client_socket 要移除的客户端套接字
     */
    void remove_client(SOCKET client_socket) {
        // 锁定客户端列表
        std::lock_guard<std::mutex> lock(clients_mutex);

        // 查找客户端套接字在列表中的位置
        auto it = std::find(clients.begin(), clients.end(), client_socket);

        // 如果找到则从列表中移除
        if (it != clients.end()) {
            clients.erase(it);
        }
    }

    /**
     * 服务器运行循环
     */
    void run() {
        // 客户端计数器（用于生成唯一客户端名称）
        int client_count = 0;

        // 主循环
        while (running) {
            // 客户端地址结构
            struct sockaddr_in client_addr;
            // 客户端地址结构大小
#ifdef _WIN32
            int client_len = sizeof(client_addr);
#else
            socklen_t client_len = sizeof(client_addr);
#endif

            // 接受新的客户端连接（阻塞调用）
            SOCKET client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_len);

            // 检查是否能够成功接受
            if (client_socket == INVALID_SOCKET) {
                // 接受失败，继续等待下一个连接
                continue;
            }

            // 获取客户端IP地址用于显示
            char client_ip[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);

            // 锁定客户端列表
            std::lock_guard<std::mutex> lock(clients_mutex);

            // 检查是否达到最大客户端数量
            if (clients.size() >= MAX_CLIENTS) {
                // 发送服务器已满消息
                std::string msg = "服务器已满，无法连接\n";
#ifdef _WIN32
                send(client_socket, msg.c_str(), (int)msg.length(), 0);
#else
                send(client_socket, msg.c_str(), msg.length(), 0);
#endif

                // 关闭新连接的套接字
                closesocket(client_socket);

                // 继续等待下一个连接
                continue;
            }

            // 将新客户端添加到客户端列表
            clients.push_back(client_socket);

            // 增加客户端计数器
            client_count++;

            // 生成客户端名称（包含IP地址）
            std::string client_name = "客户端" + std::to_string(client_count) + "[" + client_ip + "]";

            // 输出连接信息到服务器控制台
            std::cout << client_name << " 已连接" << std::endl;
            std::cout << "当前在线客户端数: " << clients.size() << std::endl;

            // 发送欢迎消息给新客户端
            std::string welcome_msg = "欢迎来到聊天平台！您的昵称: " + client_name + "\n";
#ifdef _WIN32
            send(client_socket, welcome_msg.c_str(), (int)welcome_msg.length(), 0);
#else
            send(client_socket, welcome_msg.c_str(), welcome_msg.length(), 0);
#endif

            // 创建线程处理客户端
            std::thread client_thread(&ChatServer::handle_client, this, client_socket, client_name);

            // 分离线程使其在后台运行，避免线程等待
            client_thread.detach();
        }
    }

    /**
     * 停止服务器并清理资源
     */
    void stop() {
        // 将运行标志设为false
        running = false;

        // 关闭服务器套接字
        if (server_socket != INVALID_SOCKET) {
            closesocket(server_socket);
            server_socket = INVALID_SOCKET;
        }

        // 关闭所有客户端连接
        std::lock_guard<std::mutex> lock(clients_mutex);
        for (SOCKET client : clients) {
            closesocket(client);
        }
        // 清空客户端列表
        clients.clear();

        // 输出服务器停止信息
        std::cout << "服务器已停止" << std::endl;
    }
};

/**
 * 主函数 - 程序入口
 * @return 程序退出状态码
 */
int main() {
    // 创建聊天服务器实例
    ChatServer server;

    // 启动服务器，端口8080
    if (!server.start(8080)) {
        // 启动失败，程序退出
        return 1;
    }

    // 输出服务器运行信息
    std::cout << "服务器运行中... 按Ctrl+C停止" << std::endl;
    std::cout << "支持Windows和Linux客户端连接" << std::endl;

    // 进入服务器运行循环
    server.run();

    // 程序退出
    return 0;
}
//telnet 127.0.0.1 8080